package component;


import Main.Main;
import org.fife.ui.rtextarea.RTextArea;
import ui.FontChooser;
import ui.HomePage;
import ui.IconDialog;
import util.FileUtils;
import util.GsonUils;
import util.ImageUtils;

import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.io.File;
import java.util.Deque;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author zhongwen
 * @description 定制菜单栏，包括逻辑界面和交换处理
 * @date 2021-12-08 23:05
 */
public class MenuBar extends JMenuBar {
    private final String spaces = "               ";
    private Deque<String> recentlyAdded;
    /**
     * 声明文件菜单
     */
    private final JMenu fileJMenu = new JMenu("文件");
    private final JMenu newJMenu = new JMenu("新建" + spaces);
    private final JMenuItem newJavaClassItem = new JMenuItem("Java Class" + spaces);
    private final JMenuItem openJMenuItem = new JMenuItem("打开" + spaces);
    private final JMenu recentJMenu = new JMenu("最近的文件" + spaces);
    private final JMenuItem saveJMenuItem = new JMenuItem("保存文件" + spaces);
    private final JMenuItem othersaveJMenuItem = new JMenuItem("另存为" + spaces);
    private final JMenuItem closeFileJMenuItem = new JMenuItem("关闭" + spaces);
    private final JMenuItem closeAllFilesJMenuItem = new JMenuItem("关闭所有文件" + spaces);
    private final JMenuItem overJMenuItem = new JMenuItem("退出" + spaces);
    /**
     * 声明编辑菜单
     */
    private final JMenu editMenu = new JMenu("编辑");
    private final JMenuItem cancelItem = new JMenuItem("撤销" + spaces);
    private final JMenuItem reDoItem = new JMenuItem("恢复" + spaces);
    private final JMenuItem cutItem = new JMenuItem("剪切" + spaces);
    private final JMenuItem copyItem = new JMenuItem("复制" + spaces);
    private final JMenuItem pasteItem = new JMenuItem("粘贴" + spaces);
    private final JMenuItem findItem = new JMenuItem("查找" + spaces);

    /**
     * 声明视图菜单
     */
    private final JMenu viewMenu = new JMenu("视图");
    private final JMenuItem fontItem = new JMenuItem("字体" + spaces);
    private final JMenuItem iconWidthAndHeight = new JMenuItem("图标宽高" + spaces);

    /**
     * 声明配置菜单
     */
    private final JMenu configurationMenu = new JMenu("配置");
    private final JMenuItem jdkPath = new JMenuItem("JDK路径" + spaces);

    /**
     * 声明运行菜单
     */
    private final JMenu runMenu = new JMenu("运行");
    private final JMenuItem testJDK = new JMenuItem("测试JDK" + spaces);
    private final JMenuItem compileJava = new JMenuItem("编译" + spaces);
    private final JMenuItem runJava = new JMenuItem("运行" + spaces);
    private final JMenuItem complieCmd = new JMenuItem("指定命令编译" + spaces);
    private final JMenuItem runCmd = new JMenuItem("指定命令运行" + spaces);
    private final JMenuItem cmd = new JMenuItem("运行终端命令" + spaces);


    private final JMenu aboutMenu = new JMenu("关于");
    private final JMenuItem helpJMenuItem = new JMenuItem("帮助" + spaces);
    private final JMenuItem information = new JMenuItem("介绍"  + spaces);

    /**
     * 主界面分割面板，响应事件时需要与其交互
     */
    private TablePane tablePane;

    private TopToolBar topToolBar;

    public MenuBar() {
        init();
    }

    public MenuBar(TablePane tablePane, TopToolBar topToolBar) {
        this.tablePane = tablePane;
        this.topToolBar = topToolBar;
        init();
        addListeners();
    }

    private void init() {
        // 组装文件菜单
        newJavaClassItem.setIcon(new ImageIcon(ImageUtils.getImage("class.png", Main.configurationBean.getImageWidthAndHeight(), Main.configurationBean.getImageWidthAndHeight())));
        newJMenu.add(newJavaClassItem);
        newJavaClassItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, InputEvent.CTRL_MASK));
        fileJMenu.add(newJMenu);
        fileJMenu.add(openJMenuItem);
        openJMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_MASK));
        recentJMenu.setIcon(new ImageIcon(ImageUtils.getImage("openFile.png", Main.configurationBean.getImageWidthAndHeight(), Main.configurationBean.getImageWidthAndHeight())));
        fileJMenu.add(recentJMenu);
        fileJMenu.addSeparator();
        saveJMenuItem.setIcon(new ImageIcon(ImageUtils.getImage("saveFileGray.png", Main.configurationBean.getImageWidthAndHeight(), Main.configurationBean.getImageWidthAndHeight())));
        fileJMenu.add(saveJMenuItem);
        saveJMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_MASK));
        fileJMenu.add(othersaveJMenuItem);
        fileJMenu.add(closeFileJMenuItem);
        fileJMenu.add(closeAllFilesJMenuItem);
        fileJMenu.addSeparator();
        fileJMenu.add(overJMenuItem);

        // 将最近打开的文件目录加载到内存中
        this.recentlyAdded = topToolBar.getRecentlyAdded();
        if (Main.configurationBean.getRecentFiles() != null) {
            for (String s : Main.configurationBean.getRecentFiles()) {
                JMenuItem jMenuItem = new JMenuItem(s);
                recentJMenu.add(jMenuItem);
                recentlyAdded.add(s);
                jMenuItem.addActionListener(new AbstractAction() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        // 保证一个文件只能显示在一个选项页面中
                        int tabCount = tablePane.getTabCount();
                        Map<String, Integer> map = new HashMap<>();
                        for (int i = 0; i < tabCount; i++) {
                            ClassTab classTab = (ClassTab) tablePane.getTabComponentAt(i);
                            if (classTab.getTextFile() != null) {
                                map.put(classTab.getTextFile().getAbsolutePath(), i);
                            }
                        }
                        if (map.containsKey(s)) {
                            tablePane.setSelectedIndex(map.get(s));
                        } else {
                            ClassTab tab = tablePane.addAndReturnClass();
                            JavaEditorPane javaText = (JavaEditorPane) tablePane.getComponentAt(tablePane.indexOfTabComponent(tab));
                            tab.setTextFile(new File(s));
                            tab.changeFileName(tab.getTextFile().getName());
                            RTextArea textArea = javaText.getTextArea();
                            String charset = FileUtils.getFileEncode(tab.getTextFile());
                            System.out.println("现在打开的文本编码为" + charset);
                            List<String> temp = FileUtils.openFilesWithList(tab.getTextFile(), charset);
                            StringBuilder openFileString = new StringBuilder();
                            for (int i = 0; i < temp.size() - 1; i++) {
                                openFileString.append(temp.get(i) + "\n");
                            }
                            if (temp.size() > 0) {
                                openFileString.append(temp.get(temp.size() - 1));
                            }
                            textArea.setText(openFileString.toString());
                            textArea.requestFocus();
                            if (recentlyAdded.size() >= 5) {
                                recentlyAdded.poll();
                                recentlyAdded.addLast(s);
                            } else {
                                recentlyAdded.addLast(s);
                            }
                        }
                    }
                });
            }
        }

        // 组装编辑菜单
        editMenu.add(cancelItem);
        cancelItem.setIcon(new ImageIcon(ImageUtils.getImage("cancel.png", Main.configurationBean.getImageWidthAndHeight(), Main.configurationBean.getImageWidthAndHeight())));
        cancelItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Z, InputEvent.CTRL_MASK));
        editMenu.add(reDoItem);
        editMenu.addSeparator();
        editMenu.add(cutItem);
        cutItem.setIcon(new ImageIcon(ImageUtils.getImage("cut.png", Main.configurationBean.getImageWidthAndHeight(), Main.configurationBean.getImageWidthAndHeight())));
        cutItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, InputEvent.CTRL_MASK));
        editMenu.add(copyItem);
        copyItem.setIcon(new ImageIcon(ImageUtils.getImage("copy.png", Main.configurationBean.getImageWidthAndHeight(), Main.configurationBean.getImageWidthAndHeight())));
        copyItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_MASK));
        editMenu.add(pasteItem);
        pasteItem.setIcon(new ImageIcon(ImageUtils.getImage("paste.png", Main.configurationBean.getImageWidthAndHeight(), Main.configurationBean.getImageWidthAndHeight())));
        pasteItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, InputEvent.CTRL_MASK));


        // 组装视图菜单
        viewMenu.add(fontItem);
        viewMenu.add(iconWidthAndHeight);

        // 组装配置菜单
        configurationMenu.add(jdkPath);

        // 组装运行菜单
        runMenu.add(testJDK);
        runMenu.addSeparator();
        compileJava.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.ALT_MASK));
        runMenu.add(compileJava);
        runJava.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_R, InputEvent.ALT_MASK));
        runMenu.add(runJava);
        runMenu.addSeparator();
        runMenu.add(complieCmd);
        runMenu.add(runCmd);
        runMenu.add(cmd);

        // 组装关于菜单栏
        aboutMenu.add(helpJMenuItem);
        aboutMenu.add(information);

        // 组装菜单栏
        this.add(fileJMenu);
        this.add(editMenu);
        this.add(viewMenu);
        this.add(configurationMenu);
        this.add(runMenu);
        this.add(aboutMenu);
    }

    private void addListeners() {
        newJavaClassItem.addActionListener(new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                tablePane.addClass();
            }
        });

        saveJMenuItem.addActionListener(new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                topToolBar.saveFile();
            }
        });

        openJMenuItem.addActionListener(new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                topToolBar.openFile();
            }
        });

        othersaveJMenuItem.addActionListener(new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // 带后缀名过滤器
                FileNameExtensionFilter filter = new FileNameExtensionFilter("Java源文件(*.java)", "java");
                // 当前选中的编辑页面
                JavaEditorPane selectedText = (JavaEditorPane) tablePane.getSelectedComponent();
                if (selectedText == null) {
                    JOptionPane.showMessageDialog(HomePage.jf, "请新建文件！");
                    return;
                }
                // 当前选中的选项卡
                int selectedIndex = tablePane.getSelectedIndex();
                ClassTab selectedTab = (ClassTab) tablePane.getTabComponentAt(selectedIndex);
                String text = selectedText.getTextArea().getText();
                JFileChooser otherSaveChooser = new JFileChooser(Main.configurationBean.getNowPath()) {
                    @Override
                    public void approveSelection() {
                        File selectedFile = this.getSelectedFile();
                        if (selectedFile != null) {
                            String name = selectedFile.getName();
                            if (!name.contains(".java") && this.getFileFilter().equals(filter)) {
                                selectedFile = new File(this.getCurrentDirectory() + "/" + name + ".java");
                                name = selectedFile.getName();
                            } else {
                                selectedFile = new File(this.getCurrentDirectory() + "/" + name);
                                name = selectedFile.getName();
                            }
                            if (selectedFile.exists()) {
                                int i = JOptionPane.showConfirmDialog(HomePage.jf, "是否替换已存在的" + "\"" +
                                        selectedFile.getAbsolutePath() + "\"", "CodeEasy", JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE, null);
                                if (i == JOptionPane.YES_OPTION) {
                                    FileUtils.saveFile(selectedFile, text, BottomBar.encodeButton.getText());
                                    selectedTab.changeFileName(name);
                                    selectedTab.setTextFile(selectedFile);
                                    super.approveSelection();
                                }
                            } else {
                                FileUtils.saveFile(selectedFile, text, BottomBar.encodeButton.getText());
                                selectedTab.changeFileName(name);
                                selectedTab.setTextFile(selectedFile);
                                super.approveSelection();
                            }
                        }
                    }
                };
                String name = FileUtils.getDefaultName(text);
                if (name != null) {
                    otherSaveChooser.setSelectedFile(new File(name));
                } else {
                    otherSaveChooser.setSelectedFile(new File(selectedTab.getFileName()));
                }
                otherSaveChooser.setFileFilter(filter);
                otherSaveChooser.showSaveDialog(HomePage.jf);
            }
        });

        closeFileJMenuItem.addActionListener(new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                int index = tablePane.getSelectedIndex();
                if (index != -1) {
                    tablePane.removeClass(index);
                } else {
                    JOptionPane.showMessageDialog(HomePage.jf, "请选择文件！", "提醒", JOptionPane.PLAIN_MESSAGE, null);
                }
            }
        });

        closeAllFilesJMenuItem.addActionListener(new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                closeAllFiles();
            }
        });

        overJMenuItem.addActionListener(new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                closeAllFiles();
                System.exit(0);
            }
        });
        cancelItem.addActionListener(new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                JavaTextArea javaTextArea = getJavaTextArea();
                if (javaTextArea != null) {
                    javaTextArea.undoLastAction();
                }
            }
        });

        reDoItem.addActionListener(new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                JavaTextArea javaTextArea = getJavaTextArea();
                if (javaTextArea != null) {
                    javaTextArea.redoLastAction();
                }
            }
        });
        cutItem.addActionListener(new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                JavaTextArea javaTextArea = getJavaTextArea();
                if (javaTextArea != null) {
                    javaTextArea.cut();
                }
            }
        });

        copyItem.addActionListener(new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                JavaTextArea javaTextArea = getJavaTextArea();
                if (javaTextArea != null) {
                    javaTextArea.copy();
                }
            }
        });

        pasteItem.addActionListener(new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                JavaTextArea javaTextArea = getJavaTextArea();
                if (javaTextArea != null) {
                    javaTextArea.paste();
                }
            }
        });

        iconWidthAndHeight.addActionListener(new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                IconDialog iconDialog = new IconDialog(HomePage.jf, "图标宽高选择器", true);
                iconDialog.setVisible(true);
            }
        });

        fontItem.addActionListener(new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                Font nowFont = Main.configurationBean.getFont();
                FontChooser fontChooser = new FontChooser();
                fontChooser.showDialog(HomePage.jf, "字体选择框", true, nowFont);
                Font newFont = fontChooser.getResFont();
                Main.configurationBean.setFont(newFont);
                GsonUils.objectToString(Main.configurationBean);
                int count = tablePane.getTabCount();
                for (int i = 0; i < count; i++) {
                    JavaEditorPane javaEditorPane = (JavaEditorPane) tablePane.getComponentAt(i);
                    SwingUtilities.invokeLater(new Runnable() {
                        @Override
                        public void run() {
                            javaEditorPane.getTextArea().setFont(newFont);
                        }
                    });
                }
            }
        });

        jdkPath.addActionListener(new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                JFileChooser jdkPathChooser = new JFileChooser(Main.configurationBean.getJdkPath());
                jdkPathChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
                jdkPathChooser.showOpenDialog(HomePage.jf);
                File selectedJDKPath = jdkPathChooser.getSelectedFile();
                if (selectedJDKPath != null) {
                    Main.configurationBean.setJdkPath(selectedJDKPath);
                    GsonUils.objectToString(Main.configurationBean);
                }
            }
        });

        compileJava.addActionListener(new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                topToolBar.compile();
            }
        });

        runJava.addActionListener(new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                topToolBar.run();
            }
        });

        complieCmd.addActionListener(new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                topToolBar.compileCmd();
            }
        });

        runCmd.addActionListener(new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                topToolBar.runCmd();
            }
        });

        cmd.addActionListener(new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                topToolBar.cmd();
            }
        });
        helpJMenuItem.addActionListener(new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                JOptionPane.showMessageDialog(HomePage.jf,"代码仓库地址：https://gitee.com/zhongwen0822/code-easy",
                        "帮助",JOptionPane.PLAIN_MESSAGE, null);
            }
        });

        information.addActionListener(new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                JOptionPane.showMessageDialog(HomePage.jf,"名称：CodeEasy\n作者：钟文\n完成日期：2021.12.28\n说明：XTUJava课程设计",
                        "介绍",JOptionPane.PLAIN_MESSAGE, null);
            }
        });
    }

    private JavaTextArea getJavaTextArea() {
        int index = tablePane.getSelectedIndex();
        if (index == -1) {
            return null;
        }
        JavaEditorPane javaEditorPane = (JavaEditorPane) tablePane.getComponentAt(index);
        return (JavaTextArea) javaEditorPane.getTextArea();
    }

    private void closeAllFiles() {
        int count = tablePane.getTabCount();
        for (int i = 0; i < count; i++) {
            ClassTab tabI = (ClassTab) tablePane.getTabComponentAt(0);
            tablePane.setSelectedIndex(0);
            tabI.needSaveFile();
            tablePane.removeClass(0);
        }
    }
}
